/*	$Id: start.S,v 1.3 2004/05/17 10:39:22 wlin Exp $ */

/*
 * Copyright (c) 2001 Opsycon AB  (www.opsycon.se)
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Opsycon AB, Sweden.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#ifndef _KERNEL
#define _KERNEL
#endif

#include <asm.h>
#include <regnum.h>
#include <cpu.h>
#include <pte.h>


#include "pmon/dev/ns16550.h"
#include "target/i82371eb.h"
#include "target/prid.h"
#include "target/sbd.h"
#include "target/bonito.h"
#include "target/i8254.h"
#include "target/pc97307.h"
#include "target/isapnpreg.h"
#define DEBUG_LOCORE
#undef	DEBUG_DIMM_SPD
#ifdef DEBUG_LOCORE
#define	TTYDBG(x) \
	.rdata;98: .asciz x; .text; la a0, 98b; bal stringserial; nop
#else
#define TTYDBG(x)
#endif
#define	PRINTSTR(x) \
	.rdata;98: .asciz x; .text; la a0, 98b; bal stringserial; nop


#define tmpsize		s1
#define msize		s2
#define sdShape		s3
#define bonito		s4
#define dbg		s5
#define sdCfg		s6

#define	CFG_IB 0x00000020
#define CFG_DB 0x00000010
#define CFG_C_WBACK 3
#define CFG_BE 0x00008000
#define CFG_EPMASK 0x0f000000
#define CFG_EPD 0x00000000
#define CFG_EM_R4K 0x00000000
#define CFG_EMMASK 0x00c00000
#define CFG_AD 0x00800000

/*
 *   Register usage:
 *
 *	s0	link versus load offset, used to relocate absolute adresses.
 *	s1	free
 *	s2	memory size.
 *	s3	sdShape.
 *	s4	Bonito base address.
 *	s5	dbg.
 *	s6	sdCfg.
 *	s7	rasave.
 *	s8	L3 Cache size.
 */


	.set	noreorder
	.globl	_start
	.globl	start
	.globl	__main
_start:
start:
	.globl	stack
stack = start - 0x4000		/* Place PMON stack below PMON start in RAM */

/* NOTE!! Not more that 16 instructions here!!! Right now it's FULL! */
	mtc0	zero, COP_0_STATUS_REG
	mtc0	zero, COP_0_CAUSE_REG
	li	t0, SR_BOOT_EXC_VEC	/* Exception to Boostrap Location */
	mtc0	t0, COP_0_STATUS_REG
	la	sp, stack
	la	gp, _gp

	bal	uncached		/* Switch to uncached address space */
	nop

	bal	locate			/* Get current execute address */
	nop

uncached:
	or	ra, UNCACHED_MEMORY_ADDR
	j	ra
	nop

/*
 *  Reboot vector usable from outside pmon.
 */
	.align	8
ext_map_and_reboot:
	bal	CPU_TLBClear
	nop

	li	a0, 0xc0000000
	li	a1, 0x40000000
	bal	CPU_TLBInit
	nop
	la	v0, tgt_reboot
	la	v1, start
	subu	v0, v1
	lui	v1, 0xffc0
	addu	v0, v1
	jr	v0
	nop

/*
 *  Exception vectors here for rom, before we are up and running. Catch
 *  whatever comes up before we have a fully fledged exception handler.
 */
	.align	9			/* bfc00200 */
	la	a0, v200_msg
	bal	stringserial
	nop
	b	exc_common

	.align	7			/* bfc00280 */
	la	a0, v280_msg
	bal	stringserial
	nop
	b	exc_common

/* Cache error */
	.align	8			/* bfc00300 */
	PRINTSTR("\r\nPANIC! Unexpected Cache Error exception! ")
	mfc0	a0, COP_0_CACHE_ERR
	bal	hexserial
	nop
	b	exc_common

/* General exception */
	.align	7			/* bfc00380 */
	la	a0, v380_msg
	bal	stringserial
	nop
	b	exc_common
	
	.align	8			/* bfc00400 */
	la	a0, v400_msg
	bal	stringserial
	nop


	
exc_common:
	PRINTSTR("\r\nERRORPC=")
	mfc0	a0, COP_0_ERROR_PC
	bal	hexserial
	nop
	PRINTSTR("\r\nEPC=")
	mfc0	a0, COP_0_EXC_PC
	bal	hexserial
	nop
	PRINTSTR("\r\nDERR0=")
	cfc0	a0, COP_0_DERR_0
	bal	hexserial
	nop
	PRINTSTR("\r\nDERR1=")
	cfc0	a0, COP_0_DERR_1
	bal	hexserial
	nop
//	b	ext_map_and_reboot
	nop

	.align 8
		nop
	.align 8
	.word read
	.word write
	.word open
	.word close
	.word nullfunction
	.word printf
	.word vsprintf
	.word nullfunction
	.word nullfunction
	.word getenv
	.word nullfunction
	.word nullfunction
	.word nullfunction
	.word nullfunction


/*
 *  We get here from executing a bal to get the PC value of the current execute
 *  location into ra. Check to see if we run from ROM or if this is ramloaded.
 */
locate:
	la	s0,start
	subu	s0,ra,s0
	and	s0,0xffff0000

	li	t0,SR_BOOT_EXC_VEC
	mtc0	t0,COP_0_STATUS_REG
        mtc0    zero,COP_0_CAUSE_REG
	.set noreorder

 	li	bonito,PHYS_TO_UNCACHED(BONITO_REG_BASE)
#if 0
locate:
	la	s0, start		/* RA set from BAL above! */
	subu	s0, ra, s0		/* s0 is now load vs. link offset */
	and	s0, 0xffff0000		/* Mask off lower bits */
	mfc0    t0,COP_0_PRID
        mfc0    v0,COP_0_STATUS_REG
        mtc0    zero,COP_0_WATCH_LO
        mtc0    zero,COP_0_WATCH_HI
        and     v0,SR_SOFT_RESET                # preserve Soft Reset
        or      v0,SR_BOOT_EXC_VEC               # set Boot Exceptions
        beq     t0,0x0a11,1f            # R4200 rev 1.1: disable cache errors
        nop
	beq     t0,0x5413,1f            # R5432 rev 1.3: disable cache errors
        nop
	b       2f
	nop
1:      or      v0,SR_DIAG_DE
2:

/*
 *  Clean out and initialize the TLB
 */

	bal	CPU_TLBClear
	nop

	li	a0, 0xc0000000
	li	a1, 0x40000000
	bal	CPU_TLBInit
	nop
/*
 *  Turn off all high decoders to avoid address conflicts.
 */
        mtc0    v0,COP_0_STATUS_REG
        mtc0    zero,COP_0_CAUSE_REG
        mfc0    t1,COP_0_CONFIG
        mfc0    t2,COP_0_PRID              # get PrID
        mtc0    zero,$18                # C0_IWATCH/C0_WATCHLO
        mtc0    zero,$19                # C0_DWATCH/C0_WATCHHI
                                                                                
 	li	bonito,PHYS_TO_UNCACHED(BONITO_REG_BASE)
        
	srl     t2,8
        and     t2,0xff
        
	bne     t2,PRID_R4650,2f
        nop                                                                        
        mtc0    zero,$0                 # C0_IBASE
        mtc0    zero,$1                 # C0_IBOUND
        mtc0    zero,$2                 # C0_DBASE
        mtc0    zero,$3                 # C0_DBOUND
        b       3f
	nop
                                                                                
2:     
        and     t1,~0x3f                # set bits 5..0 only
        or      t1,CFG_IB | CFG_DB | CFG_C_WBACK

        and     t1,~CFG_EPMASK
        or      t1,CFG_EPD
        bne     t2,PRID_R5400,1f
        nop
	and     t1,~CFG_EMMASK
        or      t1,CFG_EM_R4K
        b       2f
	nop
1:      and     t1,~CFG_AD
2:      mtc0    t1,COP_0_CONFIG
3:      mfc0    t1,COP_0_STATUS_REG            # get Status
        mtc0    zero,COP_0_CAUSE_REG
        and     t1,SR_SOFT_RESET                # leave the SoftReset bit
        or      t1,SR_BOOT_EXC_VEC               # force Boot Exception Vec
        mtc0    t1,COP_0_STATUS_REG
#endif

#define MOD_MASK	0x00000003
#define MOD_B		0x00000000 /* byte "modifier" */
#define MOD_H		0x00000001 /* halfword "modifier" */
#define MOD_W		0x00000002 /* word "modifier" */
#if __mips64
#	define MOD_D		0x00000003 /* doubleword "modifier" */
#endif

#define OP_MASK		0x000000fc
#define	OP_EXIT		0x00000000 /* exit (status) */
#define OP_DELAY	0x00000008 /* delay (cycles) */
#define OP_RD		0x00000010 /* read (addr) */
#define OP_WR		0x00000014 /* write (addr, val) */
#define OP_RMW		0x00000018 /* read-modify-write (addr, and, or) */
#define OP_WAIT		0x00000020 /* wait (addr, mask, value) */

#define WR_INIT(mod,addr,val) \
	.word	OP_WR|mod,PHYS_TO_UNCACHED(addr);\
	.word	(val),0
	
#define RD_INIT(mod,addr) \
	.word	OP_RD|mod,PHYS_TO_UNCACHED(addr);\
	.word	0,0
	
#define RMW_INIT(mod,addr,and,or) \
	.word	OP_RMW|mod,PHYS_TO_UNCACHED(addr);\
	.word	(and),(or)
	
#define WAIT_INIT(mod,addr,and,or) \
	.word	OP_WAIT|mod,PHYS_TO_UNCACHED(addr);\
	.word	(mask),(val)

#define DELAY_INIT(cycles) \
	.word	OP_DELAY,(cycles);\
	.word	0,0
	
#define EXIT_INIT(status) \
	.word	OP_EXIT,(status);\
	.word	0,0

#define BONITO_INIT(r,v) WR_INIT(MOD_W,BONITO_BASE+/**/r,v)
#define BONITO_BIS(r,b) RMW_INIT(MOD_W,BONITO_BASE+(r),~0,b)
#define BONITO_BIC(r,b) RMW_INIT(MOD_W,BONITO_BASE+(r),~(b),0)
#define BONITO_RMW(r,c,s) RMW_INIT(MOD_W,BONITO_BASE+(r),~(c),s)
	
#define CFGADDR(idsel,function,reg) ((1<<(11+(idsel)))+((function)<<8)+(reg))
#define _ISABWR_INIT(mod,function,isabreg,val) \
	WR_INIT(MOD_W,BONITO_BASE+BONITO_PCIMAP_CFG,CFGADDR(PCI_IDSEL_I82371,function,isabreg)>>16) ; \
        RD_INIT(MOD_W,BONITO_BASE+BONITO_PCIMAP_CFG) ; \
	WR_INIT(mod,PCI_CFG_SPACE+(CFGADDR(PCI_IDSEL_I82371,function,isabreg)&0xffff),val)
	
#define _ISABRD_INIT(mod,function,isabreg) \
	WR_INIT(MOD_W,BONITO_BASE+BONITO_PCIMAP_CFG,CFGADDR(PCI_IDSEL_I82371,function,isabreg)>>16) ; \
        RD_INIT(MOD_W,BONITO_BASE+BONITO_PCIMAP_CFG) ; \
	RD_INIT(mod,PCI_CFG_SPACE+(CFGADDR(PCI_IDSEL_I82371,function,isabreg)&0xffff))


#define _ISAWR_INIT(isareg,val) \
	WR_INIT(MOD_B,PCI_IO_SPACE+(isareg),val)
	
#define _ISARD_INIT(isareg) \
	RD_INIT(MOD_B,PCI_IO_SPACE+(isareg))
	

#define ISABBWR_INIT(function,isabreg,val) \
	_ISABWR_INIT(MOD_B,function,(isabreg),val)
#define ISABHWR_INIT(function,isabreg,val) \
	_ISABWR_INIT(MOD_H,function,(isabreg),val)
#define ISABWWR_INIT(function,isabreg,val) \
	_ISABWR_INIT(MOD_W,function,isabreg,val)
#define ISAWR_INIT(isareg,val) \
	_ISAWR_INIT(isareg,val)
#define ISARD_INIT(isareg) \
	_ISARD_INIT(isareg)

	bal	1f	
	nop

	/* bonito endianess */
	BONITO_BIC(BONITO_BONPONCFG,BONITO_BONPONCFG_CPUBIGEND)
	BONITO_BIC(BONITO_BONGENCFG,BONITO_BONGENCFG_BYTESWAP|BONITO_BONGENCFG_MSTRBYTESWAP)
	BONITO_BIS(BONITO_BONPONCFG, BONITO_BONPONCFG_IS_ARBITER)
	
        /*
         * In certain situations it is possible for the Bonito ASIC
         * to come up with the PCI registers uninitialised, so do them here
         */
#define PCI_CLASS_BRIDGE		0x06
#define PCI_CLASS_SHIFT			24
#define PCI_SUBCLASS_BRIDGE_HOST	0x00
#define PCI_SUBCLASS_SHIFT		16
#define PCI_COMMAND_IO_ENABLE		0x00000001
#define PCI_COMMAND_MEM_ENABLE		0x00000002
#define PCI_COMMAND_MASTER_ENABLE	0x00000004
#define PCI_COMMAND_STATUS_REG		0x04
#define PCI_MAP_IO			0X00000001
#define	PCI_DEV_I82371			17
#define PCI_CFG_SPACE			BONITO_PCICFG_BASE

        BONITO_INIT(BONITO_PCICLASS,(PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT) | (PCI_SUBCLASS_BRIDGE_HOST << PCI_SUBCLASS_SHIFT))
	BONITO_INIT(BONITO_PCICMD, BONITO_PCICMD_PERR_CLR|BONITO_PCICMD_SERR_CLR|BONITO_PCICMD_MABORT_CLR|BONITO_PCICMD_MTABORT_CLR|BONITO_PCICMD_TABORT_CLR|BONITO_PCICMD_MPERR_CLR)
	BONITO_INIT(BONITO_PCILTIMER, 0)
	BONITO_INIT(BONITO_PCIBASE0, 0)
	BONITO_INIT(BONITO_PCIBASE1, 0)
	BONITO_INIT(BONITO_PCIBASE2, 0)
	BONITO_INIT(BONITO_PCIEXPRBASE, 0)
	BONITO_INIT(BONITO_PCIINT, 0)

	BONITO_BIS(BONITO_PCICMD, BONITO_PCICMD_PERRRESPEN)
	
	BONITO_BIS(BONITO_PCICMD, PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE)
	
	/* enable i/o buffer cache and other go faster bits */
	BONITO_BIS(BONITO_BONGENCFG, \
			BONITO_BONGENCFG_BUSERREN| \
			BONITO_BONGENCFG_PREFETCHEN| \
			BONITO_BONGENCFG_WBEHINDEN| \
			BONITO_BONGENCFG_PCIQUEUE| \
			BONITO_BONGENCFG_SNOOPEN)
	
       BONITO_BIC(BONITO_BONGENCFG, 0x80)  #½ûÖ¹iobc

#      BONITO_BIS(BONITO_BONGENCFG, BONITO_BONGENCFG_BUSERREN)

	/* Set debug mode */
	BONITO_BIS(BONITO_BONGENCFG, BONITO_BONGENCFG_DEBUGMODE)
	/* Turn most special purpose pins into GPIO; set ISA mode */
	ISABWWR_INIT(0, I82371_GENCFG, I82371_GENCFG_CFG)
	
	/* disable RTC & KBD chip selects */
	ISABHWR_INIT(0, I82371_XBCS, 0)
	
	/* Enable PCI 2.1 timing support */
	ISABBWR_INIT(0, I82371_DLC, I82371_DLC_DT /* | I82371_DLC_PR */ | I82371_DLC_USBPR | I82371_DLC_DTTE)

	/* Set top of memory to 16MB, so all ISA bus master & DMA
	   accesses are forwarded to PCI mem space
	 */
	ISABBWR_INIT(0, I82371_TOM, I82371_TOM_TOM(16) | I82371_TOM_FWD_LBIOS | I82371_TOM_FWD_AB | I82371_TOM_FWD_89)
	
	/* Set the SMB base address */
	ISABWWR_INIT(3, I82371_PCI3_SMBBA, SMB_PORT|PCI_MAP_IO)
	/* enable the host controller */
	ISABBWR_INIT(3, I82371_PCI3_SMBHSTCFG, I82371_PCI3_SMB_HST_EN)
	/* enable the SMB IO ports */
	ISABBWR_INIT(3, PCI_COMMAND_STATUS_REG, PCI_COMMAND_IO_ENABLE)
	
	ISABWWR_INIT(3, I82371_PCI3_PMBA, 0x8000|PCI_MAP_IO)
	ISABBWR_INIT(3, I82371_PCI3_PMREGMISC, 0x01)
	
/* 15us ISA bus refresh clock */
#define ISAREFRESH (PT_CRYSTAL/(1000000/15))
	ISARD_INIT(CTC_PORT+PT_CONTROL)
	
	/* program i8254 ISA refresh counter */
	ISAWR_INIT(CTC_PORT+PT_CONTROL,PTCW_SC(PT_REFRESH)|PTCW_16B|PTCW_MODE(MODE_RG))
	ISAWR_INIT(CTC_PORT+PT_REFRESH, ISAREFRESH & 0xff)
	ISAWR_INIT(CTC_PORT+PT_REFRESH, ISAREFRESH >> 8)

	/* program ISA ICU */
	ISAWR_INIT(ICU1_PORT,  0x11) /* ICW1 */
	ISAWR_INIT(ICU1_PORT+1,0x00) /* ICW2: vector */
	ISAWR_INIT(ICU1_PORT+1,0x04) /* ICW3: cascade on IRQ2 */
	ISAWR_INIT(ICU1_PORT+1,0x01) /* ICW4: 8086 mode */
	ISAWR_INIT(ICU1_PORT+1,0xff) /* OCW1: mask all */

	ISAWR_INIT(ICU2_PORT,  0x11) /* ICW1 */
	ISAWR_INIT(ICU2_PORT+1,0x08) /* ICW2: vector */
	ISAWR_INIT(ICU2_PORT+1,0x02) /* ICW3:  */
	ISAWR_INIT(ICU2_PORT+1,0x01) /* ICW4: 8086 mode */
	ISAWR_INIT(ICU2_PORT+1,0xff) /* OCW1: mask all */
		
	ISAWR_INIT(ICU1_PORT+1,~(1<<2)) /* enable IRQ2 */
        /* set up ISA devices */
        
        /* select logical device 1 (mouse) */
        ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_LOGICAL_DEV_NUM)
        ISAWR_INIT(ISAPNP_MBDATA,1)
        ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_ACTIVATE)
        ISAWR_INIT(ISAPNP_MBDATA,1)
                                                                               
        /* select logical device 4 (parallel) */
        ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_LOGICAL_DEV_NUM)
        ISAWR_INIT(ISAPNP_MBDATA,4)
        ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_IO_DESC0+ISAPNP_IO_BASE_15_8)
        ISAWR_INIT(ISAPNP_MBDATA,(ECP_PORT>>8) & 0xff)
        ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_IO_DESC0+ISAPNP_IO_BASE_7_0)
        ISAWR_INIT(ISAPNP_MBDATA,ECP_PORT & 0xff)
        ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_IRQ_DESC0+ISAPNP_IRQ_CONTROL)
        ISAWR_INIT(ISAPNP_MBDATA,ISAPNP_IRQ_HIGH)
        ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_ACTIVATE)
        ISAWR_INIT(ISAPNP_MBDATA,1)
                                                                               
        /* select logical device 5 (COM2) */
        ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_LOGICAL_DEV_NUM)
        ISAWR_INIT(ISAPNP_MBDATA,5)
        ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_ACTIVATE)
        ISAWR_INIT(ISAPNP_MBDATA,1)

        /* select logical device 6 (COM1) */
        ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_LOGICAL_DEV_NUM)
        ISAWR_INIT(ISAPNP_MBDATA,6)
        ISAWR_INIT(ISAPNP_MBADDR,ISAPNP_ACTIVATE)
        ISAWR_INIT(ISAPNP_MBDATA,1)
                                                                               

                                                                        
	EXIT_INIT(0)

#define	Init_Op	0
#define	Init_A0	4
#define	Init_A1	8
#define	Init_A2	12
#define	Init_Size	16

1:	move a0,ra
reginit:			/* local name */
	lw	t3, Init_Op(a0)
	lw	t0, Init_A0(a0)
	and	t4,t3,OP_MASK
	
	
	/* 
	 * EXIT(STATUS) 
	 */
	bne	t4, OP_EXIT, 8f
	nop
	move	v0,t0
	b	.done
	nop
	
	/* 
	 * DELAY(CYCLES) 
	 */
8:	bne	t4, OP_DELAY, 8f
	nop
1:	bnez	t0,1b
	subu	t0,1
	b	.next
	nop	
	/* 
	 * READ(ADDR) 
	 */
8:	bne	t4,OP_RD,8f
	nop
	and	t4,t3,MOD_MASK
	
	bne	t4,MOD_B,1f
	nop
	lbu	t5,0(t0)
	b	.next
	nop
1:	bne	t4,MOD_H,1f
	nop
	lhu	t5,0(t0)
	b	.next
	nop
1:	bne	t4,MOD_W,1f
	nop
#if __mips64
	lwu	t5,0(t0)
#else 
	lw	t5,0(t0)
#endif
	b	.next
	nop
1:	
#if __mips64
	lw	t5,0(t0)
	b	.next
	nop
#else
	b	.fatal
	nop
#endif
	
	/* 
	 * WRITE(ADDR,VAL) 
	 */
8:	bne	t4,OP_WR,8f
	nop
	lw	t1,Init_A1(a0)
	and	t4,t3,MOD_MASK
	
	bne	t4,MOD_B,1f
	nop
	sb	t1,0(t0)
	b	.next
	nop
1:	bne	t4,MOD_H,1f
	nop
	sh	t1,0(t0)
	b	.next
	nop
1:	bne	t4,MOD_W,1f
	nop
	sw	t1,0(t0)
	b	.next
	nop
	
1:	
#if __mips64
	sd	t1,0(t0)
	b	.next
	nop
#else
	b	.fatal
	nop
#endif
		
	
	/* 
	 * RMW(ADDR,AND,OR) 
	 */
8:	bne	t4,OP_RMW,8f
	nop
	lw	t1,Init_A1(a0)
	lw	t2,Init_A2(a0)
	and	t4,t3,MOD_MASK
	
	bne	t4,MOD_B,1f
	nop
	lbu	t4,0(t0)
	and	t4,t1
	or	t4,t2
	sb	t4,0(t0)
	b	.next
	nop
1:	bne	t4,MOD_H,1f
	nop
	lhu	t4,0(t0)
	and	t4,t1
	or	t4,t2
	sh	t4,0(t0)
	b	.next
	nop
1:	bne	t4,MOD_W,1f
	nop
	lw	t4,0(t0)
	and	t4,t1
	or	t4,t2
	sw	t4,0(t0)
	b	.next
	nop
	
1:		
#if __mips64
	ld	t4,0(t0)
	and	t4,t1
	or	t4,t2
	sd	t4,0(t0)
	b	.next
	nop
#else	
	b	.fatal
	nop
#endif
		
	
	/* 
	 * WAIT(ADDR,MASK,VAL) 
	 */
8:	bne	t4,OP_WAIT,8f
	nop
	lw	t1,Init_A1(a0)
	lw	t2,Init_A2(a0)
	and	t4,t3,MOD_MASK
	
	bne	t4,MOD_B,1f
	nop
3:	lbu	t4,0(t0)
	and	t4,t1
	bne	t4,t2,3b
	nop
	b	.next
	nop
1:	bne	t4,MOD_H,1f
	nop
3:	lhu	t4,0(t0)
	and	t4,t1
	bne	t4,t2,3b
	nop
	b	.next
	nop
1:	bne	t4,MOD_W,1f
	nop
3:	lw	t4,0(t0)
	and	t4,t1
	bne	t4,t2,3b
	nop
	b	.next
	nop
1:		
#if __mips64
3:	ld	t4,0(t0)
	and	t4,t1
	bne	t4,t2,3b
	nop
	b	.next
	nop
#else	
	b	.fatal	
	nop
#endif
	
	
.next:	addu	a0,Init_Size
	b	reginit	
	nop	
	
8:
.fatal:	b .done
	nop
	bal 	stuck
	nop
.done:	
	/* Initialise other low-level I/O devices */

	bal	initserial
	nop
	

	PRINTSTR("\r\nPMON2000 MIPS Initializing. Standby...\r\n")

	PRINTSTR("ERRORPC=")
	mfc0	a0, COP_0_ERROR_PC
	bal	hexserial
	nop

	PRINTSTR(" CONFIG=")
	mfc0	a0, COP_0_CONFIG
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	PRINTSTR(" PRID=")
	mfc0	a0, COP_0_PRID
	bal	hexserial
	nop
	PRINTSTR("\r\n")

	PRINTSTR("Raw word read of SMB base address: ");
	li	a0,CFGADDR(PCI_DEV_I82371,3,I82371_PCI3_SMBBA)
	li	a1,PHYS_TO_UNCACHED(PCI_CFG_SPACE)
	and	a2,a0,0xffff
	or	a1,a2
	srl	a0,16
	li	a2,BONITO_BASE+BONITO_PCIMAP_CFG
	sw	a0,BONITO_PCIMAP_CFG(bonito)
	lw	zero,BONITO_PCIMAP_CFG(bonito)
	lw	a0,(a1)
	
	li	a1,2
	bal	hexserial
	nop
	PRINTSTR("\r\n")	
	
	PRINTSTR("Raw word read of SMB HSTCFG: ");
	li	a0,CFGADDR(PCI_DEV_I82371,3,I82371_PCI3_SMBHSTCFG) # byte???
	li	a1,PHYS_TO_UNCACHED(PCI_CFG_SPACE)
	and	a2,a0,0xffff
	or	a1,a2
	srl	a0,16
	li	a2,BONITO_BASE+BONITO_PCIMAP_CFG
	sw	a0,BONITO_PCIMAP_CFG(bonito)
	lw	zero,BONITO_PCIMAP_CFG(bonito)
	lhu	a0,(a1)
	
	li	a1,2
	bal	hexserial
	nop
	PRINTSTR("\r\n")	
	
	PRINTSTR("Raw word read of SMB IO ENABLE: ");
	li	a0,CFGADDR(PCI_DEV_I82371,3,PCI_COMMAND_STATUS_REG)
	li	a1,PHYS_TO_UNCACHED(PCI_CFG_SPACE)
	and	a2,a0,0xffff
	or	a1,a2
	srl	a0,16
	li	a2,BONITO_BASE+BONITO_PCIMAP_CFG
	sw	a0,BONITO_PCIMAP_CFG(bonito)
	lw	zero,BONITO_PCIMAP_CFG(bonito)
	lw	a0,(a1)
	
	li	a1,2
	bal	hexserial
	nop
	PRINTSTR("\r\n")	

	bal	i2cdump
	nop
	
PRINTSTR("DIMM read\n")
#ifdef DEBUG_DIMM_SPD
  /*test i2c */
  li	t4,0
loop:
	li	a0,0
	move	a1,t4
	bal	i2cread
	nop
	move	a0,v0
	bal	hexserial
	nop
	PRINTSTR("\r\n")

	addu	t4,1

	li	t0,255
	bltu	t4,t0,loop
	nop
#endif
	/* 
	 * Now determine DRAM configuration and size by
	 * reading the I2C EEROM on the DIMMS
	 */
	li	msize,0


	/* start with SODIMM #0 */
	li	a0,0
	li	sdCfg,0
	
.nextdimm:
	li	sdShape,0
	
	/* read DIMM memory type (must be SDRAM) */
	li	a1,2
	bal	i2cread
	nop
	bne	v0,4,.nodimm
	nop
	PRINTSTR("read memory type\r\n")
	/* read DIMM memory size per side */
	li	a1,31
	bal	i2cread
	nop
	beqz	v0,.nodimm
	nop
	sll	tmpsize,v0,22		# multiply by 4M
	
	PRINTSTR("read memory size per side\r\n")
	/* read DIMM number of rows */
	li	a1,3
	bal	i2cread
	nop	
	subu	v0,11
	bgtu	v0,14-11,.nodimm
	nop
	sll	v0,BONITO_SDCFG_AROWBITS_SHIFT
	and	v0,BONITO_SDCFG_AROWBITS
	or	sdShape,v0
	
	PRINTSTR("read number of rows\r\n")
2:	/* read DIMM number of cols */
	li	a1,4
	bal	i2cread
	nop
	subu	v0,8
	bgtu	v0,11-8,.nodimm
	nop
	sll	v0,BONITO_SDCFG_ACOLBITS_SHIFT
	and	v0,BONITO_SDCFG_ACOLBITS
	or	sdShape,v0
	
	PRINTSTR("read number of col\r\n")
2:	/* read DIMM number of blocks-per-dram */
	li	a1,17
	bal	i2cread
	nop
	beq	v0,2,2f
	nop
	bne	v0,4,.nodimm
	nop
	or	sdShape,BONITO_SDCFG_ABANKBIT
	
	PRINTSTR("read blocks per dram\r\n")
2:	/* read DIMM number of sides (banks) */
	li	a1,5
	bal	i2cread
	nop
	beq	v0,1,2f
	nop
	bne	v0,2,.nodimm
	nop
	or	sdShape,BONITO_SDCFG_ASIDES
	sll	tmpsize,1	# msize *= 2	
	
	PRINTSTR("read number of sides\r\n")
2:	/* read DIMM width */
	li	a1,6
	bal	i2cread
	nop
	bleu	v0,36,2f
	nop
	bgtu	v0,72,.nodimm
	nop
	or	sdShape,BONITO_SDCFG_AWIDTH64
	
	PRINTSTR("read width\r\n")
2:	addu	msize,tmpsize
	b	2f
	nop	
.nodimm:
#ifdef DBGSBD
	move	dbg,a0
	PRINTSTR ("\r\niNo DIMM in slot ")
	move	a0,dbg
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	move	a0,dbg
#endif	
	or	sdShape,BONITO_SDCFG_AABSENT
2:	beqz	a0,1f
	nop
	sll	sdShape,BONITO_SDCFG_BROWBITS_SHIFT
1:	or	sdCfg,sdShape
	
	move dbg,a0
	PRINTSTR("DIMM0 in slot")
	move a0,dbg
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	move a0,dbg
      	PRINTSTR("DIMM1...\n")
      	move a0,dbg

	addu	a0,1
	bltu	a0,2,.nextdimm
	nop
	PRINTSTR("DIMM SIZE=")
	move	a0,msize
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	/* If we are running in SDRAM, chop 4MB off the memory size,
	   and don't modify sdCfg register (assume someone in 
	   PCI-world has already set it up). */
	lw	t0,BONITO_BONPONCFG(bonito)
	and	t0,BONITO_BONPONCFG_ROMBOOT
	bne	t0,BONITO_BONPONCFG_ROMBOOT_SDRAM,1f
	nop
	beqz	msize,2f	# already zero!
	nop
	subu	msize,-1
	b	2f
	nop
1:	sw	sdCfg,BONITO_SDCFG(bonito)
	
2:	b	3f	
	nop
.skipdimm:
	li	msize,4*0x100000
3:
#ifdef DBGSBD
	PRINTSTR("sdcfg=");
	move	a0,sdCfg
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
#endif

	li	t1,0		# accumulate pcimembasecfg settings
		
	/* set bar0 mask and translation to point to SDRAM */
	sub	t0,msize,1
	not	t0
	srl	t0,BONITO_PCIMEMBASECFG_ASHIFT-BONITO_PCIMEMBASECFG_MEMBASE0_MASK_SHIFT
	and	t0,BONITO_PCIMEMBASECFG_MEMBASE0_MASK
	or	t1,t0
	
	li	t0,0x00000000
	srl	t0,BONITO_PCIMEMBASECFG_ASHIFT-BONITO_PCIMEMBASECFG_MEMBASE0_TRANS_SHIFT
	and	t0,BONITO_PCIMEMBASECFG_MEMBASE0_TRANS
	or	t1,t0
	or	t1,BONITO_PCIMEMBASECFG_MEMBASE0_CACHED

	/* set bar1 to minimum size to conserve PCI space */
	li	t0, ~0
	srl	t0,BONITO_PCIMEMBASECFG_ASHIFT-BONITO_PCIMEMBASECFG_MEMBASE1_MASK_SHIFT
	and	t0,BONITO_PCIMEMBASECFG_MEMBASE1_MASK
	or	t1,t0
	
	li	t0,0x00000000
	srl	t0,BONITO_PCIMEMBASECFG_ASHIFT-BONITO_PCIMEMBASECFG_MEMBASE1_TRANS_SHIFT
	and	t0,BONITO_PCIMEMBASECFG_MEMBASE1_TRANS
	or	t1,t0
	or	t1,BONITO_PCIMEMBASECFG_MEMBASE1_CACHED

	sw	t1,BONITO_PCIMEMBASECFG(bonito)

	/* enable configuration cycles now */
	lw	t0,BONITO_BONPONCFG(bonito)
	and	t0,~BONITO_BONPONCFG_CONFIG_DIS
	sw	t0,BONITO_BONPONCFG(bonito)


	PRINTSTR("Init SDRAM Done!\r\n");
/*
 *  Reset and initialize caches to a known state.
 */
#define IndexStoreTagI	0x08
#define IndexStoreTagD	0x09
#define IndexStoreTagS	0x0b
#define IndexStoreTagT	0x0a
#define FillI		0x14

/*
 *  RM7000 config register bits.
 */
#define CF_7_SE         (1 << 3)        /* Secondary cache enable */
#define CF_7_SC         (1 << 31)       /* Secondary cache not present */
#define CF_7_TE         (1 << 12)       /* Tertiary cache enable */
#define CF_7_TC         (1 << 17)       /* Tertiary cache not present */
#define CF_7_TS         (3 << 20)       /* Tertiary cache size */
#define CF_7_TS_AL      20              /* Shift to align */
#define NOP8 nop;nop;nop;nop;nop;nop;nop;nop
do_caches:
	TTYDBG("Sizing caches...\r\n");

	mfc0	t3, COP_0_CONFIG	/* t3 = original config */
	and	t3, 0xffffeff0		/* Make sure coherency is OK */

	and	t3, ~(CF_7_TE|CF_7_SE|CF_7_TC|CF_7_SC)  /* disable L2/L3 cache */
	mtc0    t3, COP_0_CONFIG
#if 0
	li	t2, 4096

	srl	t1, t3, 9
	and	t1, 3

	sllv	s3, t2, t1		/* s3 = I cache size */

	and	t1, t3, 0x20
	srl	t1, t1, 1
	addu	s4, t1, 16		/* s4 = I cache line size */

	srl	t1, t3, 6
	and	t1, 3
	sllv	s5, t2, t1		/* s5 = D cache size */

	and	t1, t3, 0x10
	addu	s6, t1, 16		/* s6 = D cache line size */
#endif
	TTYDBG("Init caches...\r\n")
#if 0
	li	s7, 0                   /* no L2 cache */
	li	s8, 0                   /* no L3 cache */
#endif

	TTYDBG("godson1 caches found\r\n")
       bal     godson1_cache_init
       nop

#ifdef DEBUG_LOCORE
	TTYDBG("Init caches done, cfg = ")
	mfc0	a0, COP_0_CONFIG
	bal	hexserial
	nop
	TTYDBG("\r\n")
#endif

	TTYDBG("Copy PMON to execute location...\r\n")
#ifdef DEBUG_LOCORE
	TTYDBG("start = ")
	la	a0, start
	bal	hexserial
	nop
	TTYDBG("\r\ncopytoram = ")
	la	a0, copytoram
	addu	a0, s0
	bal	hexserial
	nop
	TTYDBG("\r\ns0 = ")
	move	a0, s0
	bal	hexserial
	nop
	TTYDBG("\r\n")
#endif
	la	a0, start
	li	a1, 0xbfc00000
	la	a2, _edata
        or      a0, 0xa0000000
        or      a2, 0xa0000000
	subu	t1, a2, a0
	srl t1, t1, 2

	move	t0, a0
	move	t1, a1
	move	t2, a2

	/* copy text section */
	
1:	and	t3,t0,0x0000ffff
	bnez	t3,2f
	nop
	move	a0,t0
	bal	hexserial
	nop
	li	a0,'\r'
	bal 	tgt_putchar
	nop
2:	lw	t3, 0(t1)
	nop
	sw	t3, 0(t0)
	addu	t0, 4
	addu	t1, 4
	bne t2, t0, 1b
	nop

	PRINTSTR("copy text section done.\r\n")
	
	/* Clear BSS */
	la	a0, _edata
	la	a2, _end
2:	sw	zero, 0(a0)
	bne a2, a0, 2b
	addu	a0, 4


	TTYDBG("Copy PMON to execute location done.\r\n")

	/*sw	0, CpuTertiaryCacheSize*/ /* Set L3 cache size */
	
	move	a0,	msize
	srl	a0,20
	la	v0, initmips
	jalr	v0
	nop
stuck:
#ifdef DEBUG_LOCORE
	TTYDBG("Dumping GT64240 setup.\r\n")
	TTYDBG("offset----data------------------------.\r\n")
	li	s3, 0
1:
	move	a0, s3
	bal	hexserial
	nop
	TTYDBG(": ")
2:
	add	a0, s3, bonito
	lw	a0, 0(a0)
	bal	hexserial
	addiu	s3, 4
	TTYDBG(" ")
	li	a0, 0xfff
	and	a0, s3
	beqz	a0, 3f
	li	a0, 0x01f
	and	a0, s3
	bnez	a0, 2b
	TTYDBG("\r\n")
	b	1b
	nop
3:
	b	3b
	nop

#else
	b	stuck
	nop
#endif
/*
 *  Clear the TLB. Normally called from start.S.
 */
#if __mips64
#define MTC0 dmtc0
#else 
#define MTC0 mtc0
#endif
LEAF(CPU_TLBClear)
	li	a3, 0			# First TLB index.

	li	a2, PG_SIZE_4K
	MTC0   a2, COP_0_TLB_PG_MASK   # Whatever...

1:
	MTC0   zero, COP_0_TLB_HI	# Clear entry high.
	MTC0   zero, COP_0_TLB_LO0	# Clear entry low0.
	MTC0   zero, COP_0_TLB_LO1	# Clear entry low1.

	mtc0    a3, COP_0_TLB_INDEX	# Set the index.
	addiu	a3, 1
	li	a2, 64
	nop
	nop
	tlbwi				# Write the TLB

	bne	a3, a2, 1b
	nop

	jr	ra
	nop
END(CPU_TLBClear)

/*
 *  Set up the TLB. Normally called from start.S.
 */
LEAF(CPU_TLBInit)
	li	a3, 0			# First TLB index.

	li	a2, PG_SIZE_16M
	MTC0   a2, COP_0_TLB_PG_MASK   # All pages are 16Mb.

1:
	and	a2, a0, PG_SVPN
	MTC0   a2, COP_0_TLB_HI	# Set up entry high.

	move	a2, a0
	srl	a2, a0, PG_SHIFT 
	and	a2, a2, PG_FRAME
	ori	a2, PG_IOPAGE
	MTC0   a2, COP_0_TLB_LO0	# Set up entry low0.
	addu	a2, (0x01000000 >> PG_SHIFT)
	MTC0   a2, COP_0_TLB_LO1	# Set up entry low1.

	mtc0    a3, COP_0_TLB_INDEX	# Set the index.
	addiu	a3, 1
	li	a2, 0x02000000
	subu	a1, a2
	nop
	tlbwi				# Write the TLB

	bgtz	a1, 1b
	addu	a0, a2			# Step address 32Mb.

	jr	ra
	nop
END(CPU_TLBInit)

/*
 * Simple character printing routine used before full initialization
 */
#if 0
#define		TXWAIT	0x100000
LEAF(tgt_putchar)
        /* blocking transmit, with timeout */
        li      t0,TXWAIT                       # timeout
1:      lbu     t1,PHYS_TO_UNCACHED(0x1fd002fd)       # get LSR
        and     t1,0x20                 # tx ready?
        bnez    t1,1f                           # yup - go and write
	nop
        subu    t0,1                            # continue until timeout
        bnez    t0,1b
	nop
1:      sb      a0,PHYS_TO_UNCACHED(0x1fd002f8)               # write data
        li      t0,TXWAIT                       # timeout
1:      lbu     t1,PHYS_TO_UNCACHED(0x1fd003fd)       # get LSR
        and     t1,0x20                 # tx ready?
        bnez    t1,1f                           # yup - go and write
	nop
        subu    t0,1                            # continue until timeout
        bnez    t0,1b
	nop
1:      sb      a0,PHYS_TO_UNCACHED(0x1fd003f8)               # write data
	j	ra
	nop
END(tgt_putchar)
#endif

LEAF(stringserial)
	move	a2, ra
	addu	a1, a0, s0
	lbu	a0, 0(a1)
1:
	beqz	a0, 2f
	nop
	bal	tgt_putchar
	addiu	a1, 1
	b	1b
	lbu	a0, 0(a1)

2:
	j	a2
	nop
END(stringserial)
LEAF(outstring)
	move	a2, ra
	move	a1, a0
	lbu	a0, 0(a1)
1:
	beqz	a0, 2f
	nop
	bal	tgt_putchar
	addiu	a1, 1
	b	1b
	lbu	a0, 0(a1)

2:
	j	a2
	nop
END(outstring)
LEAF(hexserial)
	move	a2, ra
	move	a1, a0
	li	a3, 7
1:
	rol	a0, a1, 4
	move	a1, a0
	and	a0, 0xf
	la	v0, hexchar
	addu	v0, s0
	addu	v0, a0
	bal	tgt_putchar
	lbu	a0, 0(v0)

	bnez	a3, 1b
	addu	a3, -1

	j	a2
	nop
END(hexserial)
LEAF(tgt_putchar)
	la	v0, COM1_BASE_ADDR
1:
	lbu	v1, NSREG(NS16550_LSR)(v0)
	and	v1, LSR_TXRDY
	beqz	v1, 1b
	nop

	sb	a0, NSREG(NS16550_DATA)(v0)

	j	ra
	nop	
END(tgt_putchar)
/* baud rate definitions, matching include/termios.h */
#define B0      0
#define B50     50      
#define B75     75
#define B110    110
#define B134    134
#define B150    150
#define B200    200
#define B300    300
#define B600    600
#define B1200   1200
#define B1800   1800
#define B2400   2400
#define B4800   4800
#define B9600   9600
#define B19200  19200
#define B38400  38400
#define B57600  57600
#define B115200 115200

LEAF(initserial)
	la	v0, COM1_BASE_ADDR
1:
	li	v1, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_4
	sb	v1, NSREG(NS16550_FIFO)(v0)
	li	v1, CFCR_DLAB
	sb	v1, NSREG(NS16550_CFCR)(v0)
 	li	v1, NS16550HZ/(16*CONS_BAUD)
	sb	v1, NSREG(NS16550_DATA)(v0)
	srl	v1, 8
	sb	v1, NSREG(NS16550_IER)(v0)
	li	v1, CFCR_8BITS
	sb	v1, NSREG(NS16550_CFCR)(v0)
#if 0
	li	v1, MCR_DTR|MCR_RTS
#endif
	sb	v1, NSREG(NS16550_MCR)(v0)
	li	v1, 0x0
	sb	v1, NSREG(NS16550_IER)(v0)

	move	v1, v0
	la	v0, COM2_BASE_ADDR
	bne	v0, v1, 1b
	nop

	j	ra
	nop
END(initserial)

#define SMBOFFS(reg) I82371_SMB_SMB##reg

LEAF(i2cdump)
	move	t4,ra
	
	li	a0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))
	lbu	a0,SMBOFFS(HSTSTS)(a0)
	li	a1,1
	bal	hexserial
	nop
	PRINTSTR("\r\n")
		
	li	a0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))
	lbu	a0,SMBOFFS(SLVSTS)(a0)
	li	a1,1
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	li	a0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))
	lbu	a0,SMBOFFS(HSTCNT)(a0)
	li	a1,1
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	li	a0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))
	lbu	a0,SMBOFFS(HSTCMD)(a0)
	li	a1,1
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	li	a0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))
	lbu	a0,SMBOFFS(HSTADD)(a0)
	li	a1,1
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	li	a0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))
	lbu	a0,SMBOFFS(HSTDAT0)(a0)
	li	a1,1
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	li	a0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))
	lbu	a0,SMBOFFS(HSTDAT1)(a0)
	li	a1,1
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	li	a0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))
	lbu	a0,SMBOFFS(BLKDAT)(a0)
	li	a1,1
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	li	a0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))
	lbu	a0,SMBOFFS(SLVCNT)(a0)
	li	a1,1
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	li	a0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))
	lbu	a0,SMBOFFS(SHDWCMD)(a0)
	li	a1,1
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	li	a0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))
	lbu	a0,SMBOFFS(SLVEVT)(a0)
	li	a1,1
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	li	a0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))
	lbu	a0,SMBOFFS(SLVDAT)(a0)
	li	a1,1
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	jr	t4
	nop
END(i2cdump)



LEAF(i2cread)
	li	t0,PHYS_TO_UNCACHED(ISAPORT_BASE(SMB_PORT))

	lbu	t1,SMBOFFS(HSTSTS)(t0)
	and	t1,~(I82371_SMB_FAILED|I82371_SMB_BUS_ERR|I82371_SMB_DEV_ERR|I82371_SMB_INTER)
	sb	t1,SMBOFFS(HSTSTS)(t0)
	
	sll	t1,a0,1
	or	t1,0xa1		# DIMM base address and read bit
	sb	t1,SMBOFFS(HSTADD)(t0)
	sb	a1,SMBOFFS(HSTCMD)(t0)
	
	
	li	t1,I82371_SMB_START|I82371_SMB_BDRW
	sb	t1,SMBOFFS(HSTCNT)(t0)

	li	t3,10000	
1:	lbu	t1,SMBOFFS(HSTSTS)(t0)
	and	t2,t1,I82371_SMB_FAILED|I82371_SMB_BUS_ERR|I82371_SMB_DEV_ERR|I82371_SMB_INTER
	bnez	t2,1f
	nop
	sub	t3,1
	bnez	t3,1b
	nop
	b	9f		
	nop
1:	
	# clear pending errors/interrupts
	sb	t1,SMBOFFS(HSTSTS)(t0)
	
	and	t2,t1,I82371_SMB_FAILED|I82371_SMB_BUS_ERR|I82371_SMB_DEV_ERR
	bnez	t2,9f
	nop
	lbu	v0,SMBOFFS(HSTDAT0)(t0)
	j	ra
	nop
	
9:	li	v0,-1
	j	ra
	nop
END(i2cread)	

__main:
	j	ra
	nop


	.rdata
transmit_pat_msg:
	.asciz	"\r\nInvalid transmit pattern.  Must be DDDD or DDxDDx\r\n"
v200_msg:
	.asciz	"\r\nPANIC! Unexpected TLB refill exception!\r\n"
v280_msg:
	.asciz	"\r\nPANIC! Unexpected XTLB refill exception!\r\n"
v380_msg:
	.asciz	"\r\nPANIC! Unexpected General exception!\r\n"
v400_msg:
	.asciz	"\r\nPANIC! Unexpected Interrupt exception!\r\n"
hexchar:
	.ascii	"0123456789abcdef"

	.text
	.align	2
/*
 *   I2C Functions used in early startup code to get SPD info from
 *   SDRAM modules. This code must be entirely PIC and RAM independent.
 */

/* Delay macro */
#define	DELAY(count)	\
	li v0, count;	\
99:			\
	bnz	vo, 99b;\
	addiu	v0, -1


#define I2C_INT_ENABLE	0x80
#define I2C_ENABLE	0x40
#define I2C_ACK		0x04
#define I2C_INT_FLAG	0x08
#define I2C_STOP_BIT	0x10
#define I2C_START_BIT	0x20

#define	I2C_AMOD_RD	0x01

#define	BUS_ERROR				0x00
#define	START_CONDITION_TRA			0x08
#define	RSTART_CONDITION_TRA			0x10
#define	ADDR_AND_WRITE_BIT_TRA_ACK_REC		0x18
#define	ADDR_AND_READ_BIT_TRA_ACK_REC		0x40
#define	SLAVE_REC_WRITE_DATA_ACK_TRA		0x28
#define	MAS_REC_READ_DATA_ACK_NOT_TRA		0x58

#define Index_Store_Tag_D			0x05
#define Index_Invalidate_I			0x00
#define Index_Writeback_Inv_D			0x01

LEAF(godson1_cache_init)
####part 2####
	.set mips3
cache_detect_2way:
	mfc0	t4, COP_0_CONFIG
	andi	t5, t4, 0x0e00
	srl	t5, t5, 9
	andi	t6, t4, 0x01c0
	srl	t6, t6, 6
	addiu	t6, t6, 11
	addiu	t5, t5, 11
	addiu	t4, $0, 1
	sllv	t6, t4, t6
	sllv	t5, t4, t5
	addiu	t7, $0, 2
####part 3####
	lui	a0, 0x8000
	addu	a1, $0, t5
	addu	a2, $0, t6
cache_init_d2way:
#a0=0x80000000, a1=icache_size, a2=dcache_size
#a3, v0 and v1 used as local registers
	mtc0	$0, COP_0_TAG_HI
	addu	v0, $0, a0
	addu	v1, a0, a2
1:	slt	a3, v0, v1
	beq	a3, $0, 1f
	nop
	mtc0	$0, COP_0_TAG_LO
	cache	Index_Store_Tag_D, 0x0(v0)
	mtc0	$0, COP_0_TAG_LO
	cache	Index_Store_Tag_D, 0x1(v0)
	beq	$0, $0, 1b
	addiu	v0, v0, 0x20
1:
cache_flush_i2way:
	addu	v0, $0, a0
	addu	v1, a0, a1
1:	slt	a3, v0, v1
	beq	a3, $0, 1f
	nop
	cache	Index_Invalidate_I, 0x0(v0)
#	cache	Index_Invalidate_I, 0x1(v0)
	beq	$0, $0, 1b
	addiu	v0, v0, 0x20
1:
cache_flush_d2way:
	addu	v0, $0, a0
	addu	v1, a0, a2
1:	slt	a3, v0, v1
	beq	a3, $0, 1f
	nop
	cache	Index_Writeback_Inv_D, 0x0(v0)
	cache	Index_Writeback_Inv_D, 0x1(v0)
	beq	$0, $0, 1b
	addiu	v0, v0, 0x20
1:
cache_init_finish:
	nop
	jr	ra
	nop

cache_init_panic:
	TTYDBG("cache init panic\r\n");
1:	b	1b
	nop
	.set mips2
END(godson1_cache_init)
LEAF(nullfunction)
	jr ra
	nop
END(nullfunction)
